#ifndef _SHM_HPP_
#define _SHM_HPP_

#include <iostream>
#include <cstring>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>

#define PATH_NAME "."
#define PROJ_ID  0x60

#define SHM_SIZE 4096

key_t getKey()
{
    key_t key = ftok(PATH_NAME, PROJ_ID);
    if(key < 0/*key == -1*/)
    {
        std::cerr << "get key of shm errno:" << errno << " -> " << strerror(errno) << std::endl;
        exit(1);// key获取失败，无法创建共性内存，就没有再进行下去的必要了
    }
    return key;
}

int getShmHelp(key_t key, int flags)
{
    int shmId = shmget(key, SHM_SIZE, flags);
    if(shmId < 0/*-1*/)
    {
        std::cerr << "shmget errno:" << errno << " -> " << strerror(errno);
        exit(2);
    }
    return shmId;
}

// 创建共享内存 -- server
int createShm(key_t/*int*/ key)
{
    return getShmHelp(key, IPC_CREAT | IPC_EXCL | 0600);
}
// 访问/打开共享内存 -- client
int getShm(key_t key)
{
    return getShmHelp(key, IPC_CREAT);
}

// 连接共享内存
void* attachShm(int shmId)
{
    // void *shmat(int shmid, const void *shmaddr, int shmflg);
    void* start = shmat(shmId, nullptr, 0);
    if((long long)start == -1)
    {
        std::cerr << "shmat errno:" << errno << " -> " << strerror(errno);
        exit(3);
    }
    return start;
}

// 取消连接
void deleteAttach(const void* shmAddr)
{
    // int shmdt(const void *shmaddr);
    int ret = shmdt(shmAddr);
    if(ret < 0/*-1*/)
    {
        std::cerr << "shmdt errno:" << errno << " -> " << strerror(errno);
        // exit(4);
    }
}

// 删除共享内存
void deleteShm(int shmId)
{
    // int shmctl(int shmid, int cmd, struct shmid_ds *buf);
    int delCode = shmctl(shmId, IPC_RMID, nullptr);
    if(delCode < 0/*-1*/)
    {
        std::cerr << "delete shm -> shmctl errno:" << errno << " -> " << strerror(errno);
        // exit(5);
    }
}

#endif